package jbase.project.system.net.http;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Map;

import jbase.project.system.core.common.EventHook;

public class HttpService {
	private boolean CONTINUE_ACCEPT_REQUEST = true;
	private String ip;
	private int port;
	private ServerSocket serverSocket;
	private boolean isActive = false;
	private boolean workAsProxy;

	private EventHook eventHook;

	public HttpService(EventHook hook, String ip, int port, boolean workAsProxy) {
		this.ip = ip;
		this.port = port;
		this.eventHook = hook;
		this.workAsProxy = workAsProxy;
	}

	public HttpService(EventHook hook, String ip, int port) {
		this(hook, ip, port, false);
	}

	public Status activeServer(Map<String, Object> config) {
		if (this.isActive == true) {
			return Status.IS_HAS_ACTIVED;
		}
		try {
			InetSocketAddress address = new InetSocketAddress(this.ip, this.port);
			this.serverSocket = new ServerSocket();
			this.serverSocket.bind(address);
			this.CONTINUE_ACCEPT_REQUEST = true;
		} catch (IOException e) {
			close();
			eventHook.event("exception", e.getMessage());
			return Status.IS_CANNOT_OPENPORT;
		}

		new Thread(new AsyncService(eventHook, config, serverSocket, this)).start();

		return Status.IS_SUCCESS;
	}

	public void close() {
		this.CONTINUE_ACCEPT_REQUEST = false;
		try {
			this.serverSocket.close();
		} catch (Exception e) {
			eventHook.event("exception", e.getMessage());
		}
	}

	/**
	 * 附加结构数据-----------------------------------------------------------------------------------------------
	 */
	public static enum Status {
		IS_HAS_ACTIVED(), IS_CANNOT_OPENPORT, IS_SUCCESS;
	}

	public static class WorkThread implements Runnable {
		private Socket client;
		private Map<String, Object> config;
		private EventHook hook;
		private boolean workAsProxy;

		public WorkThread(EventHook hook, Socket socket, Map<String, Object> config, boolean workAsProxy) {
			this.hook = hook;
			this.client = socket;
			this.config = config;
			this.workAsProxy = workAsProxy;
		}

		public WorkThread(EventHook hook, Socket socket, Map<String, Object> config) {
			this(hook, socket, config, false);
		}

		public void run() {
			try {
				OutputStream httpOut = client.getOutputStream();
				InputStream httpIn = client.getInputStream();
				if (this.workAsProxy) {
					HttpProxyNetService service = new HttpProxyNetService(hook, httpIn, httpOut, config);
					service.doService();
				} else {
					HttpNetService service = new HttpNetService(hook, httpIn, httpOut, config);
					service.doService();
				}
			} catch (IOException e) {
				hook.event("exception", e.getMessage());
			}
		}
	}

	public static class AsyncService implements Runnable {
		private EventHook hook;
		private ServerSocket serverSocket;
		private HttpService http;
		private Map<String, Object> config;

		public AsyncService(EventHook hook, Map<String, Object> config, ServerSocket serverSocket,
				HttpService httpService) {
			this.hook = hook;
			this.serverSocket = serverSocket;
			this.http = httpService;
			this.config = config;
		}

		@Override
		public void run() {
			while (http.CONTINUE_ACCEPT_REQUEST) {
				Socket clientSocket = null;
				try {
					http.isActive = true;
					clientSocket = serverSocket.accept();
				} catch (IOException e) {
					hook.event("exception", e.getMessage());
					http.CONTINUE_ACCEPT_REQUEST = false;
					continue;
				}
				if (clientSocket != null) {
					WorkThread work = new WorkThread(this.hook, clientSocket, this.config, http.workAsProxy);
					new Thread(work).start();
				} else {
					hook.event("message", "--产生了一個無效的連接！--");
				}
			}
		}
	}

}
